﻿using InnovTech.Data.Dropbox;
using InnovTech.Util.Crypto;
using System.Collections.ObjectModel;
using System.IO;
using AppLimit.CloudComputing.SharpBox;
using InnovTech.Util.Workflow;
using System;
using InnovTech.Data.Dropbox.Commands;

namespace Dropbox.DataHouse.Logic
{
    public class DataHouseModel
    {
        string fileInfosListName = "list";
        string fileInfosListDir = "/DataWare";
        string dataDir = "/DataWare/Data";


        private DropboxClient _dropboxClient;

        public DropboxClient DropboxClient
        {
            get
            {
                if (_dropboxClient == null)
                    _dropboxClient = CreateStorage();
                return _dropboxClient;
            }
        }

        private DropboxClient CreateStorage()
        {

            StreamCryptor cryptor = new RijndaelCryptor();

            DropboxLoginInfo login = null;
            using(FileStream fs = File.OpenRead(Directory.GetCurrentDirectory() + "\\accessToken"))
            {
                login = cryptor.Decrypt(fs) as DropboxLoginInfo;
                 fs.Close();
                
            }

            return new DropboxClient(login, cryptor);
        }

        public ObservableCollection<FileInformation> GetFileInfos()
        {
            ObservableCollection<FileInformation> list = null;
            DropboxClient.Execute(() => 
            {
                GetFileList(out list);
            });
            return list;
        }

        public FileInformation AddNewFile(string newFilePath, FileOperationProgressChanged progressChanged = null)
        {
            FileInfo info = new FileInfo(newFilePath);

            ObservableCollection<FileInformation> list = null;
            FileInformation fi = new FileInformation() 
                                { 
                                    Name = Path.GetFileName(newFilePath), 
                                    Dir = dataDir,
                                    Length = info.Length,
                                    LastModification = info.LastWriteTime,
                                };
            
            DropboxClient.Execute(() => 
                {
                    DropboxClient.Upload(newFilePath, dataDir, Path.GetFileName(newFilePath), progressChanged);
                    DropboxClient.Open();
                    GetFileList(out list);
                    list.Add(fi);
                    UpdateFileInfoList(list);
                });
            return fi;
        }


        private void GetFileList(out ObservableCollection<FileInformation> list)
        {
            try
            {
                list = DropboxClient.Deserialize(fileInfosListName, fileInfosListDir) as ObservableCollection<FileInformation>;
            }
            catch
            {
                list = new ObservableCollection<FileInformation>();
            }
            
        }

        public FileInformation DeleteFile(ObservableCollection<FileInformation> fileInfos, FileInformation fileToDelete)
        {

            DropboxClient.Execute(() =>
            {
                DropboxClient.Delete(fileToDelete.Name, fileToDelete.Dir);
                ObservableCollection<FileInformation> newList = new ObservableCollection<FileInformation>(fileInfos);
                newList.Remove(fileToDelete);
                //fileInfos.Remove(fileToDelete);
                UpdateFileInfoList(newList);
            });
            return fileToDelete;
        }

        public FileInformation DeleteFile(ObservableCollection<FileInformation> fileInfos, 
            FileInformation fileToDelete, Action start, Action completed,
            Action deleteStarting, Action updateStarting, FileOperationProgressChanged updateProgress)
        {

            Workflow wf = new Workflow();
            if (start != null)
                wf.Starting += (sender, args) => { start(); };
            if (completed != null)
                wf.Completed += (sender, args) => { completed(); };

            WorkStep delete = new WorkStep(() => 
            {
                DropboxClient.Open();
                DropboxClient.Delete(fileToDelete.Name, fileToDelete.Dir);
            });
            delete.Starting += (sender, args) => deleteStarting();


            WorkStep updateList = new WorkStep(() =>
            {
                ObservableCollection<FileInformation> newList = new ObservableCollection<FileInformation>(fileInfos);
                newList.Remove(fileToDelete);
                DropboxClient.Open();
                UpdateFileInfoList(newList, updateProgress);
            });
            updateList.Starting += (sender, args) => updateStarting();
            
            wf.AddStep(delete);
            wf.AddNextStep(delete, updateList);

            wf.Run();

            return fileToDelete;
        }

        public void DownloadFile(FileInformation fileToDownload, string targetPath, FileOperationProgressChanged progressChanged = null)
        {
            DropboxClient.Execute(() =>
                {
                    DropboxClient.Download(fileToDownload.Name, fileToDownload.Dir, targetPath, progressChanged);
                });
        }

        private void UpdateFileInfoList(ObservableCollection<FileInformation> fileInfos, FileOperationProgressChanged progressChanged = null)
        {
            DropboxClient.Serialize(fileInfos, fileInfosListName, fileInfosListDir, progressChanged);
        }
    }
}
